function addRow(tableId, cells) {
	var tableElem = document.getElementById(tableId);
	var newRow = tableElem.insertRow(-1);
	var newCell;
	for ( var i = 0; i < cells.length; i++) {
		newCell = newRow.insertCell(-1);
		newCell.innerHTML = cells[i];
	}
}

function addSingleColumnRow(tableId, value) {
	var tableElem = document.getElementById(tableId);
	var newRow;
	var newCell;
	var lastRow;
	var colCount = 0;
	if (tableElem.rows.length >= 1) {
		lastRow = tableElem.rows[tableElem.rows.length - 1];
		for ( var i = 0; i < lastRow.cells.length; i++) {
			if (lastRow.cells[i]) {
				colCount += lastRow.cells[i].colSpan;
			}
		}
	}
	newRow = tableElem.insertRow(-1);
	newCell = newRow.insertCell(-1);
	newCell.innerHTML = value;
	if (colCount) {
		newCell.colSpan = colCount;
	}
}

function clean(tableId, clearHeader) {
	var tableElem = document.getElementById(tableId);
	while (tableElem.rows.length > 1) {
		tableElem.deleteRow(-1);
	}
	// delete header
	if (clearHeader) {
		tableElem.deleteRow(-1);
	}
}

function populateTable(options) {
	if (options.root && options.tableId && options.xmlDoc) {
		var root = options.root;
		var tableId = options.tableId;
		var xmlDoc = options.xmlDoc;
		var value;
		if (root && tableId && xmlDoc) {

			var children = xmlDoc.getElementsByTagName(root)[0].childNodes;
			if (children && children.length > 0) {
				var headers = new Array();
				clean(tableId, options.generateHeader);
				if (options.generateHeader) {
					for ( var i = 0; i < children.length; i++) {
						headers.push(children[i].nodeName);
					}
					addRow(tableId, headers, options.headerOptions);
				}
				for ( var i = 0; i < children.length; i++) {
					var grandchildren = children[i].childNodes;
					var contents = new Array();
					if (!options.criteria || check(grandchildren, options.criteria)) {
						if (options.firstColumnCheckBox) {
							contents
									.push('<input type="checkbox" name="selActs" value="'
											+ children[i].attributes
													.getNamedItem("id").value
											+ '" />');
						}
						for ( var j = 0; j < grandchildren.length; j++) {
							value = grandchildren[j].textContent;
							if (options.colOptions && options.colOptions[j]) {
								if (options.colOptions[j].type == "date") {
									var opts = new Object;
									try {
										opts.dayIndex = 2;
										opts.monthIndex = 1;
										opts.yearIndex = 0;
										// need dateUtil.js
										value = toDate(value, opts);
										value = value.toDateString();
									} catch (e) {
										value = grandchildren[j].textContent;
									}
								}
							}
							contents.push(value);
						}
						addRow(tableId, contents);
					}
				}
				
			} else {
				clean(tableId, options.generateHeader);
				addSingleColumnRow(tableId, "No data");
			}
		}
	}
}

function check(nodes, criteria) {
	var pass = true;
	var criterion;
	var fieldValue;
	try {
		if (criteria && nodes) {
			for ( var i = 0; i < criteria.length; i++) {
				criterion = criteria[i];
				switch (criterion.type) {
				case "date":
					fieldValue = dateFromString(nodes[criterion.field].textContent);
					break;
				default:
					fieldValue = nodes[criterion.field].textContent;
					break;
				}

				switch (criterion.operator) {
				case "eq":
					pass = (fieldValue == criterion.value);
					break;
				case "gt":
					pass = (fieldValue > criterion.value);
					break;
				case "lt":
					pass = (fieldValue < criterion.value);
					break;
				case "ge":
					pass = (fieldValue >= criterion.value);
					break;
				case "le":
					pass = (fieldValue <= criterion.value);
					break;
				default:
					break;
				}
				// stop checking when not pass
				if (pass == false) {
					break;
				}
			}
		}
	} catch (e) {
		alert(e);
		return false;
	}
	return pass;
}